﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using XDesigner.Development.Dom ;
using System.IO;

namespace XDesigner.Development.Controls
{
    /// <summary>
    /// XDD main form
    /// </summary>
    /// <remarks>Written by yuan yong fu</remarks>
    public partial class frmSolutionBrowser : Form
    {
        public frmSolutionBrowser()
        {
            InitializeComponent();
            _FormTitle = this.Text;
        }

        private string _FormTitle = null;


        private SolutionInfo _CurrentSolution = new SolutionInfo();

        private CopyOptions _CurrentCopyOptions = null;

        private void frmSolutionBrowser_Load(object sender, EventArgs e)
        {
            _CurrentCopyOptions = Properties.Settings.Default.CopyOptions;
             if (_CurrentCopyOptions == null)
             {
                 _CurrentCopyOptions = new CopyOptions();
                 Properties.Settings.Default.CopyOptions = _CurrentCopyOptions;
             }
        }


        private void btnOpen_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog dlg = new OpenFileDialog())
            {
                dlg.CheckFileExists = true;
                dlg.ShowReadOnly = false;
                dlg.Filter = DevStrings.SolutionFileFilter;
                if (dlg.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
                {
                    OpenSolution(dlg.FileName);
                }
            }
        }


        private void OpenSolution(string fileName)
        {
            this.Cursor = Cursors.WaitCursor;
            if (_CurrentSolution.Load(fileName))
            {
                tvwSolution.BeginUpdate();
                tvwSolution.Nodes.Clear();
                TreeViewHelper.Fill(tvwSolution.ImageList, _CurrentSolution);
                TreeViewHelper.Fill(tvwSolution, _CurrentSolution);
                tvwSolution.Nodes[0].Expand();
                tvwSolution.EndUpdate();
                this.Text = fileName + " - " + _FormTitle;
            }
            else
            {
                MessageBox.Show(this, string.Format(DevStrings.FailToLoadFile_FileName, fileName), this.Text);
            }
            this.Cursor = Cursors.Default;
        }

        private void btnLineCount_Click(object sender, EventArgs e)
        {
            LineCount();
        }

        private void LineCount()
        {
            System.ComponentModel.BackgroundWorker worker = new BackgroundWorker( );
            worker.WorkerReportsProgress = true;
            worker.DoWork += new DoWorkEventHandler(worker_DoWork);
            worker.ProgressChanged += delegate(object sender, ProgressChangedEventArgs e)
                {
                    myProgressBar.Value = e.ProgressPercentage;
                };
            myProgressBar.Value = 0;
            myProgressBar.Visible = true;
            this.Cursor = Cursors.WaitCursor;
            worker.RunWorkerAsync(_CurrentSolution);
            worker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e)
            {
                myProgressBar.Visible = false;
                foreach (Control ctl in pnlWorkspace.Controls)
                {
                    ctl.Visible = false;
                }
                lvwLineCount.Visible = true;
                lvwLineCount.Dock = DockStyle.Fill;
                lvwLineCount.BeginUpdate();
                lvwLineCount.Items.Clear();
                lvwLineCount.SmallImageList = tvwSolution.ImageList;
                SourceFileInfo totalFile = new SourceFileInfo();
                int totalFilesCount = 0;
                for (int iCount = 0; iCount < _CurrentSolution.Projects.Count; iCount++)
                {
                    ProjectInfo prj = _CurrentSolution.Projects[iCount];
                    ListViewItem prjItem = new ListViewItem(prj.Name + "[" + DevStrings.Total + "]");
                    prjItem.ImageKey = System.IO.Path.GetExtension(prj.ProjectFileName);
                    
                    SourceFileInfo prjTotalFile = new SourceFileInfo();
                    if ((iCount % 2) == 1)
                    {
                        prjItem.BackColor = System.Drawing.Color.SkyBlue;
                    }
                    prjItem.ForeColor = Color.Red;
                    int prjFilesCount = 0;
                    lvwLineCount.Items.Add(prjItem);
                    foreach (SourceFileInfo file in prj.Files)
                    {
                        if (file.Handled)
                        {
                            prjFilesCount++;
                            totalFilesCount++;
                            prjTotalFile.BlankCount += file.BlankCount;
                            prjTotalFile.CharCount += file.CharCount;
                            prjTotalFile.CodeCount += file.CodeCount;
                            prjTotalFile.CommentCount += file.CommentCount;
                            prjTotalFile.FileSize += file.FileSize;
                            prjTotalFile.LineCount += file.LineCount;

                            totalFile.BlankCount += file.BlankCount;
                            totalFile.CharCount += file.CharCount;
                            totalFile.CodeCount += file.CodeCount;
                            totalFile.CommentCount += file.CommentCount;
                            totalFile.FileSize += file.FileSize;
                            totalFile.LineCount += file.LineCount;
                            totalFile.Time += file.Time;

                            ListViewItem item = new ListViewItem("  " + Path.GetFileName(file.FileName));
                            item.SubItems.Add(XDesigner.Common.FileHelper.FormatByteSize(file.FileSize));
                            item.SubItems.Add(file.CharCount.ToString());
                            item.SubItems.Add(file.LineCount.ToString());
                            item.SubItems.Add(file.BlankCount.ToString());
                            item.SubItems.Add(file.CodeCount.ToString());
                            item.SubItems.Add(file.CommentCount.ToString());
                            if ((iCount % 2) == 1)
                            {
                                item.BackColor = System.Drawing.Color.SkyBlue;
                            }
                            item.ImageKey = Path.GetExtension(file.FileName);
                            lvwLineCount.Items.Add(item);
                        }//if
                    }//foreach
                    prjItem.Text = prj.Name + "[" + prjFilesCount + " files]";
                    prjItem.SubItems.Add(XDesigner.Common.FileHelper.FormatByteSize(prjTotalFile.FileSize));
                    prjItem.SubItems.Add(prjTotalFile.CharCount.ToString());
                    prjItem.SubItems.Add(prjTotalFile.LineCount.ToString());
                    prjItem.SubItems.Add(prjTotalFile.BlankCount.ToString());
                    prjItem.SubItems.Add(prjTotalFile.CodeCount.ToString());
                    prjItem.SubItems.Add(prjTotalFile.CommentCount.ToString());
                }//for
                ListViewItem slnItem = new ListViewItem(_CurrentSolution.Name + "[" + totalFilesCount + " files]");
                slnItem.SubItems.Add(XDesigner.Common.FileHelper.FormatByteSize(totalFile.FileSize));
                slnItem.SubItems.Add(totalFile.CharCount.ToString());
                slnItem.SubItems.Add(totalFile.LineCount.ToString());
                slnItem.SubItems.Add(totalFile.BlankCount.ToString());
                slnItem.SubItems.Add(totalFile.CodeCount.ToString());
                slnItem.SubItems.Add(totalFile.CommentCount.ToString());
                slnItem.Font = new System.Drawing.Font(Control.DefaultFont, FontStyle.Bold);
                slnItem.ImageKey = Path.GetExtension(_CurrentSolution.FileName);
                lvwLineCount.Items.Insert(0, slnItem);
                lvwLineCount.EndUpdate();
                lblStatus.Text = string.Format(
                    DevStrings.AnalyseTotalTime_File_Time, 
                    totalFilesCount, 
                    totalFile.Time);
                this.Cursor = Cursors.Default;
            };
        }

        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = (BackgroundWorker)sender;
            SolutionInfo sln = (SolutionInfo)e.Argument;
            // get files to be analyse
            List<SourceFileInfo> files = new List<SourceFileInfo>();
            foreach (ProjectInfo prj in sln.Projects)
            {
                foreach (SourceFileInfo file in prj.Files)
                {
                    file.Handled = false;
                    if (System.IO.File.Exists(file.FullFileName) && file.Style == FileStyle.SourceCode )
                    {
                        string ext = System.IO.Path.GetExtension(file.FileName);
                        FileAnalyser analyser = FileAnalyser.GetAnalyser(ext);
                        if (analyser != null)
                        {
                            files.Add(file);
                        }
                    }
                }
            }
            for (int iCount = 0; iCount < files.Count; iCount++)
            {
                SourceFileInfo file = ( SourceFileInfo ) files[ iCount ] ;
                worker.ReportProgress((int)(iCount * 100.0 / files.Count));
                FileAnalyser analyser = FileAnalyser.GetAnalyser(System.IO.Path.GetExtension(file.FileName));
                int tickCount = System.Environment.TickCount;
                analyser.Analyse(file);
                file.Time = System.Environment.TickCount - tickCount;
                file.Handled = true;
            }
        }

        private void btnCopy_Click(object sender, EventArgs e)
        {
            CopyFile();
        }

        private void CopyFile( )
        {
            CopyOptions options = _CurrentCopyOptions;
            using (dlgCopy dlg = new dlgCopy())
            {
                dlg.InputCopyOptions = options;
                if (dlg.ShowDialog(this) == System.Windows.Forms.DialogResult.Cancel)
                {
                    return;
                }
            }
            if (options.ClearOutputDirectory)
            {
                try
                {
                    // clear output directory
                    DirectoryInfo dir = new DirectoryInfo(options.OutputDirectory);
                    foreach (FileSystemInfo info in dir.GetFileSystemInfos())
                    {
                        if (info is FileInfo)
                        {
                            info.Delete();
                        }
                        else if (info is DirectoryInfo)
                        {
                            ((DirectoryInfo)info).Delete(true);
                        }
                    }
                }
                catch (Exception ext)
                {
                    MessageBox.Show(ext.Message + Environment.NewLine + options.OutputDirectory);
                }
                System.IO.Directory.CreateDirectory(options.OutputDirectory);
            }
            List<string> sourceFiles = new List<string>();
            List<string> descFiles = new List<string>();
            Dictionary<ProjectInfo, string> prjFiles = new Dictionary<ProjectInfo, string>();
            if (options.Type == CopyType.Solution)
            {
                if (File.Exists(_CurrentSolution.FileName))
                {
                    sourceFiles.Add(_CurrentSolution.FileName);
                    descFiles.Add(Path.Combine(options.OutputDirectory, Path.GetFileName(_CurrentSolution.FileName)));
                }
                foreach (SourceFileInfo file in _CurrentSolution.Files)
                {
                    if (File.Exists(file.FullFileName))
                    {
                        sourceFiles.Add(file.FullFileName);
                        if (Path.IsPathRooted(file.FileName))
                        {
                            descFiles.Add(Path.Combine(options.OutputDirectory, Path.GetFileName(file.FileName)));
                        }
                        else
                        {
                            descFiles.Add(Path.Combine(options.OutputDirectory, file.FileName));
                        }
                    }
                }//foreach
                foreach (ProjectInfo prj in _CurrentSolution.Projects)
                {
                    if (System.IO.File.Exists(prj.ProjectFileName) == false)
                    {
                        return;
                    }
                    string dir = prj.RelativePath;
                    if (string.IsNullOrEmpty(prj.RelativePath) == false)
                    {
                        dir = System.IO.Path.Combine(options.OutputDirectory, prj.RelativePath);
                        dir = System.IO.Path.GetDirectoryName(dir);
                    }
                    else
                    {
                        dir = System.IO.Path.Combine(
                            options.OutputDirectory,
                            System.IO.Path.GetFileNameWithoutExtension(prj.ProjectFileName));
                    }
                    AddProjectFile(prj, dir, sourceFiles, descFiles, prjFiles);
                }//foreach
            }
            else
            {
                ProjectInfo currentProject = null;
                TreeNode node = tvwSolution.SelectedNode;
                while (node != null)
                {
                    if (node.Tag is ProjectInfo)
                    {
                        currentProject = (ProjectInfo)node.Tag;
                        break;
                    }
                    node = node.Parent;
                }//while
                if (currentProject == null)
                {
                    MessageBox.Show(this, DevStrings.PromptSelectProject, this.Text);
                    return;
                }
                if (File.Exists(currentProject.ProjectFileName))
                {
                    AddProjectFile(currentProject, options.OutputDirectory, sourceFiles, descFiles, prjFiles);
                }
            }
            if (sourceFiles.Count > 0)
            {
                XDesigner.WinForms.Native.ShellFileOperation so = new WinForms.Native.ShellFileOperation();
                so.ParentWindowHandle = this.Handle;
                if (so.CopyFile(sourceFiles.ToArray(), descFiles.ToArray()))
                {
                    if (options.ResetFileAttribute)
                    {
                        foreach (string fileName in descFiles)
                        {
                            File.SetAttributes(fileName, FileAttributes.Normal);
                        }//foreach
                    }
                    if (options.RemoveVSSInfo)
                    {
                        if (options.Type == CopyType.Solution)
                        {
                            if (_CurrentSolution.Style == SolutionStyle.VSSolution 
                                && File.Exists( _CurrentSolution.FileName ))
                            {
                                VSNETHelper.RemoveSolutionSourceControlInfo(descFiles[0]);
                            }
                        }
                        foreach (ProjectInfo prj in prjFiles.Keys )
                        {
                            string fileName = prjFiles[prj];
                            if (options.ResetFileAttribute == false)
                            {
                                File.SetAttributes(fileName, FileAttributes.Normal);
                            }
                            if (prj.Style == ProjectStyle.CS2003
                                || prj.Style == ProjectStyle.CS2005
                                || prj.Style == ProjectStyle.CS2008
                                || prj.Style == ProjectStyle.CS2010
                                || prj.Style == ProjectStyle.VBNET2003
                                || prj.Style == ProjectStyle.VBNET2005
                                || prj.Style == ProjectStyle.VBNET2008
                                || prj.Style == ProjectStyle.VBNET2010)
                            {
                                VSNETHelper.RemoveSourceControlInfo(prj, fileName, false);
                            }
                        }//foreach
                    }
                    // handle comment in source file
                    if (options.RemoveCommment 
                        || string.IsNullOrEmpty(options.HeaderComment) == false)
                    {
                        foreach (string fileName in descFiles)
                        {
                            FileAnalyser analyser = FileAnalyser.GetAnalyser(Path.GetExtension(fileName));
                            if (analyser != null)
                            {
                                if (options.ResetFileAttribute == false)
                                {
                                    File.SetAttributes(fileName, FileAttributes.Normal);
                                }
                                HandleCommentArgs args = new HandleCommentArgs();
                                args.HeaderComment = options.HeaderComment;
                                args.PreserveDocumentComment = options.PreserveDocumentComment;
                                args.RemoveCommment = options.RemoveCommment;
                                if (analyser.HandleComment( fileName, args ))
                                {

                                }
                            }
                        }//foreach
                    }//if
                }//if
            }//if
            MessageBox.Show(this, string.Format( DevStrings.CopyFiles_Files, sourceFiles.Count) , this.Text );
        }

        private void AddProjectFile(
            ProjectInfo prj,
            string outputDirectory,
            List<string> sourceFiles, 
            List<string> descFiles,
            Dictionary<ProjectInfo, string> prjFiles)
        {
            if (System.IO.File.Exists(prj.ProjectFileName) == false)
            {
                return ;
            }
            string descFile = Path.Combine(outputDirectory, Path.GetFileName(prj.ProjectFileName));
            sourceFiles.Add(prj.ProjectFileName);
            descFiles.Add(descFile);
            prjFiles[prj] = descFile;
            foreach (SourceFileInfo file in prj.Files)
            {
                if (File.Exists(file.FullFileName))
                {
                    sourceFiles.Add(file.FullFileName);
                    if (Path.IsPathRooted(file.FileName))
                    {
                        descFiles.Add(Path.Combine(outputDirectory, Path.GetFileName(file.FileName)));
                    }
                    else
                    {
                        descFiles.Add(Path.Combine(outputDirectory, file.FileName));
                    }
                }
            }//foreach
        }

        private void btnAbout_Click(object sender, EventArgs e)
        {
            using (dlgAbout dlg = new dlgAbout())
            {
                dlg.ShowDialog(this);
            }
        }
    }
}
